﻿ 
 
using Newtonsoft.Json;
using SHKF.B2C.Model;
using SHKF.B2C.Network;
using SHKF.B2C.YouZanYun.Model.Dto;
using SHKF.B2C.YouZanYun.Model.Dto.Plat;
using SHKF.B2C.YouZanYun.Model.Dto.ScrmCustomer;
using SHKF.B2C.YouZanYun.Model.Dto.Secret;
using SHKF.B2C.YouZanYun.Model.Dto.Token;
using SHKF.B2C.YouZanYun.Model.Inter.Category;
using SHKF.B2C.YouZanYun.Model.Inter.CategoryPropertys;
using SHKF.B2C.YouZanYun.Model.Inter.Center;
using SHKF.B2C.YouZanYun.Model.Inter.Customer.CreateMember;
using SHKF.B2C.YouZanYun.Model.Inter.Customer.CustomerCreate;
using SHKF.B2C.YouZanYun.Model.Inter.Customer.CustomerPointsIncrease;
using SHKF.B2C.YouZanYun.Model.Inter.Customer.CustomerPointsSync;
using SHKF.B2C.YouZanYun.Model.Inter.Customer.CustomerUpdate;
using SHKF.B2C.YouZanYun.Model.Inter.Image;
using SHKF.B2C.YouZanYun.Model.Inter.ImgUpload;
using SHKF.B2C.YouZanYun.Model.Inter.Item;
using SHKF.B2C.YouZanYun.Model.Inter.ItemCreate;
using SHKF.B2C.YouZanYun.Model.Inter.ItemSearch;
using SHKF.B2C.YouZanYun.Model.Inter.ItemsInventory;
using SHKF.B2C.YouZanYun.Model.Inter.MaterialCategory;
using SHKF.B2C.YouZanYun.Model.Inter.Organization;
using SHKF.B2C.YouZanYun.Model.Inter.UpdateBranch;
using SHKF.B2C.YouZanYun.Model.Inter.UpdatePrice;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
 

namespace SHFK.B2C.YouZanYun.Network
{
    public class HttpClientYzy : HttpClientBase
    {
        public string authority_id = ""; //店铺ID
         
        private long timestamp;
        public string access_token = "";


        //----------店铺 
        private const string url = "/api/youzan.shop.basic.get/3.0.0"; //获取店铺基本信如 id、名称、logo、认证类型、主页地址
         
        private const string urlBranchUpdateStock = "/api/youzan.item.update.branch.sku/1.0.0";
        private const string urlShopList = "/api/youzan.shop.chain.descendent.organization.list/1.0.0";

        private const string urlCategoryChildren = "/api/youzan.category.listchildren/1.0.0";               //查询直接子类目列表
        private const string urlMaterialCategory = "/api/youzan.material.general.category.list/1.0.0";      //图片分组
        private const string urlMaterialList     = "/api/youzan.material.general.image.list/1.0.0";         //图片列表 
        private const string urlImgUpload = "/api/youzan.materials.storage.platform.img.upload/3.0.0";      //上传图片接口

        //--产品
        private const string urlItemCategoryById = "/api/youzan.category.getbyid/1.0.0";  //根据类目id查询类目详情
       
        private const string urlItemAdd    = "/api/youzan.item.add/1.0.0";          //商品新增接口
        //private const string urlItemGet    = "/api/youzan.item.get/3.0.0";        //商品详细
        private const string urlItemGet   = "/api/youzan.item.detail.get/1.0.0";    //商品详细
        private const string urlItemsInventoryGet = "/api/youzan.items.inventory.get/3.0.0";  //获取仓库中的商品列表
        private const string urlItemSearch= "/api/youzan.item.search/3.0.0";

        //------会员
        private const string urlScrmCustomerList = "/api/youzan.scrm.customer.list/1.0.0";
        private const string urlScrmCustomerDetail = "/api/youzan.scrm.customer.detail.get.1.0.1";
        private const string urlScrmCustomerCreate = "/api/youzan.scrm.customer.create/3.0.0";
        private const string urlScrmCustomerUpdate = "/api/youzan.scrm.customer.update/3.0.0";                 //更新客户信息
        private const string urlScrmCustomerCreateMember = "/api/youzan.scrm.customer.create.member/1.0.0";   //创建会员
        private const string urlScrmCustomerPointsIncrease = "/api/youzan.crm.customer.points.increase/4.0.0"; //增加会员积分
        private const string urlScrmCustomerPointsDecrease = "/api/youzan.crm.customer.points.decrease/4.0.0"; //减少会员积分
        private const string urlScrmCustomerPointsSync = "/api/youzan.crm.customer.points.sync/4.0.0";         //同一店铺同一用户10s内只能操作一次同步积分

        private string urlDecryptBatch = "api/youzan.cloud.secret.decrypt.batch/1.0.0";

        private const string client_id = "b1e44d37dd2ff7305f";
        private const string client_secret = "8b1e25b725aadf68d3963b7b3d339c19";

        private string scrm_token = "/auth/token";
       
        
           
        /// <summary>
        /// 
        /// </summary>
        /// <param name="urlDb">有赞云的服务地址</param>
        //public HttpClientYouZanYun(string urlDb)
        //{
        //    base.BaseAddress = new Uri("https://open.youzanyun.com");
        //    this.urlDb = urlDb;
        //}

        public HttpClientYzy()
        {
            base.BaseAddress = new Uri("https://open.youzanyun.com"); 
        }

        public long GetTimeStamp()
        {
            DateTime now = DateTime.Now;
            this.timestamp = DateTimeUtil.DateTimeToLongTimeStamp(now);
            return timestamp;
        }

        #region token

        
        public async Task<TokenYZYDto> GetYouZanYunToken(bool refresh = false)
        {
            TokenYZYDto requestToken = null;

            RequestToken info = new RequestToken();
            info.authorize_type = "silent";
            info.client_id = client_id;
            info.client_secret = client_secret;
            info.grant_id = this.authority_id;
            info.refresh = refresh;

            DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(RequestToken));
            MemoryStream msObj = new MemoryStream();

            //将序列化之后的Json格式数据写入流中
            dataContractJsonSerializer.WriteObject(msObj, info);
            msObj.Position = 0;

            //从0这个位置开始读取流中的数据
            StreamReader sr = new StreamReader(msObj, Encoding.UTF8);

            string content = sr.ReadToEnd(); ;
            StringContent stringContent = new StringContent(content);

            MediaTypeHeaderValue mediaTypeHeaderValue = new MediaTypeHeaderValue("application/json");
            stringContent.Headers.ContentType = mediaTypeHeaderValue;

            HttpResponseMessage httpRequestMessage = await base.PostAsync(this.scrm_token, stringContent);

            //读取流
            if (httpRequestMessage.IsSuccessStatusCode)
            {
                string result = await httpRequestMessage.Content.ReadAsStringAsync();
                requestToken = await httpRequestMessage.Content.ReadAsAsync<TokenYZYDto>();
                //if (requestToken.code == 200)
                //{
                //    await this.SaveErpToken(requestToken);
                //} 
            }
            if( requestToken.Data != null)
            {
                this.access_token = requestToken.Data.access_token;
            } 
            return requestToken;
        }

        
        #endregion

        #region 产品

        /// <summary>
        /// 在线商品
        /// </summary>
        /// <param name="authority_id"></param>
        /// <param name="productName"></param>
        /// <returns></returns>
        public async Task<ItemsDto> GetOnSaleProduct(string authority_id,string productName)
        {
            this.authority_id = authority_id; //获取token用

            string requestUri = "/api/youzan.items.onsale.get/3.0.0";
            ItemsDto productDto = await this.TGet<ItemsDto>(requestUri, null);
            return productDto;
        }

        public async Task<ItemsInventoryResult> ItemsInventoryGet(string authority_id, ItemsInventoryParam param)
        {
            this.authority_id = authority_id; //获取token用 
            ItemsInventoryResult data = await this.TGet<ItemsInventoryResult>(urlItemsInventoryGet, null);
            return data;
        }

        /// <summary>
        /// 分页查询微商城销售中和已售罄商品列表
        /// </summary>
        /// <param name="authority_id"></param>
        /// <returns></returns>
        public async Task<ItemsDto> ItemSearch(string authority_id, string key)
        {
            this.authority_id = authority_id; //获取token用 

            ItemSearchParam itemSearchParam = new ItemSearchParam();
            itemSearchParam.q = key;
            ItemsDto data = await this.TPost<ItemsDto>(urlItemSearch, itemSearchParam);
            return data;
        }

        /// <summary>
        /// 根据类目id查询类目详情
        /// </summary>
        /// <returns></returns>
        public async Task<CategoryPropertysResult> GetCategoryById(string authority_id, long id)
        {
            this.authority_id = authority_id; //获取token用  
            Dictionary<string, object> paraList = new Dictionary<string, object>();
            paraList.Add("id", id); 
            paraList.Add("is_include_pro_value", true);
            paraList.Add("is_include_property", true);

            CategoryPropertysResult result = await this.TGet<CategoryPropertysResult>(urlItemCategoryById, paraList);
            return result; 
        }


        /// <summary>
        /// 商品新增接口
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<ItemResult> ItemAdd(string authority_id, ParamItemRequest param)
        {
            this.authority_id = authority_id; //获取token用 
            ItemResult data = await this.TPost<ItemResult>(urlItemAdd, param);
            return data;
        }

        public async Task<ItemCreateResult> ItemCreate(string authority_id, ItemCreateReqeust param)
        {
            this.authority_id = authority_id; //获取token用 
            ItemCreateResult data = await this.TPost<ItemCreateResult>(urlItemAdd, param);
            return data;
        }

        /// <summary>
        /// 商品详细
        /// </summary>
        /// <param name="item_id"></param>
        public async void ItemGet(long item_id)
        {
            await this.GetToken();

            string requestUri = base.BaseAddress.OriginalString + urlItemGet + "?access_token=" + this.access_token;
            requestUri += $"&item_id={item_id}";

            HttpResponseMessage httpResponseMessage = await base.GetAsync(requestUri);
            if (!httpResponseMessage.IsSuccessStatusCode)
            {
                string result = await httpResponseMessage.Content.ReadAsStringAsync();
            }
             
        }

        /// <summary>
        /// 获取仓库中的商品列表
        /// </summary>
        /// <param name="authority_id"></param>
        /// <param name="param"></param>

        public bool UploadFile(string groupId, List<string> filePathList)
        {
            using (var httpClient = new HttpClient())
            {
                var content = new MultipartFormDataContent
                {
                    {new StringContent(groupId), "\"GroupId\""}
                }; 

                    foreach (var filePath in filePathList)
                    {
                        var fileInfo = new FileInfo(filePath); 
                        if (!fileInfo.Exists)
                        {
                            return false;
                        }
                        
                        content.Add(new ByteArrayContent(
                        File.ReadAllBytes(filePath)), "\"file\"",  $"\"{fileInfo.Name}\"");
               }

                var response = httpClient.PostAsync("", content).Result;
                var ret = response.Content.ReadAsStringAsync().Result;

            }

            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<ImgUploadResult> ImgUpload(ImgUploadParam param)
        {
            ImgUploadResult dto = new ImgUploadResult();
            try
            {
                if (this.access_token == "")
                {
                    await this.GetToken();
                }
                 
                string uriString = urlImgUpload + "?access_token=" + this.access_token;


                //string json = JsonConvert.SerializeObject(param, settings);
                //StringContent stringContent = new StringContent(json);
                //stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json")
                
                Stream file = param.image.Open(FileMode.Open);
                var content = new MultipartFormDataContent() 
                {
                    {new StringContent(param.category_id.ToString()), "\"category_id\""},
                    {new StreamContent(file),"image",param.image.Name }
                };
            
                HttpResponseMessage httpResponseMessage = await base.PostAsync(uriString, content);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string STR = await httpResponseMessage.Content.ReadAsStringAsync();

                    dto = await httpResponseMessage.Content.ReadAsAsync<ImgUploadResult>();
                }
                else
                {
                    throw new Exception(httpResponseMessage.ToString());
                }

                return dto;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        /// <summary>
        /// 图片分组
        /// </summary>
        /// <param name="category_type"></param>
        /// <returns></returns>
        public async Task<MaterialCategoryResult> GetMaterialCategory(int category_type)
        {
            Dictionary<string, object> param = new Dictionary<string, object>();
            param.Add("partner_biz_type", 1); //业务类型，默认传值：1，1 - 店铺类型
            param.Add("category_type", category_type);   //分组类型 1-自定义，2-未分组，3-搜狗
            param.Add("media_type", 1);   //素材类型 1-图片，2-音频，3-视频

            MaterialCategoryResult result = await this.TGet<MaterialCategoryResult>(urlMaterialCategory, param);
            return result;
        }


        /// <summary>
        /// 图片列表
        /// </summary>
        /// <param name="category_id"></param>
        /// <returns></returns>
        public async Task<ImageResult> GetMaterialImageList(long category_id, int page_no = 1)
        {
            Dictionary<string, object> parmaList = new Dictionary<string, object>();
            parmaList.Add("partner_biz_type", 1);
            parmaList.Add("category_id", category_id);
            parmaList.Add("page_no", page_no);
            
            ImageResult result = await this.TGet<ImageResult>(urlMaterialList, parmaList);
            return result;
        }

        /// <summary>
        /// 查询直接子类目列表
        /// </summary>
        /// <param name="pid"> 父类目ID：查询一级时pid = 0；查询其他级别类目时传递父级ID</param>
        /// <returns></returns>
        public async Task<CategoryRequest> GetCategoryChildren(long pid =0)
        {
            Dictionary<string, object> parmaList = new Dictionary<string, object>();
            parmaList.Add("pid", pid); 

            CategoryRequest result = await this.TGet<CategoryRequest>(urlCategoryChildren, parmaList);
            return result;
        }

        #endregion

        #region shop


        /// <summary>
        /// 查询连锁总部的下级组织（即店铺）
        /// </summary>
        /// <param name="page_size"></param>
        /// <param name="page_num"></param>
        /// <returns></returns>
        public async Task<OrganizationResult> GetShopList(string authority_id, int page_size = 50, int page_num = 1)
        {
            this.authority_id = authority_id; //获取token用
            
            Dictionary<string, object> paraList = new Dictionary<string, object>(); 
            paraList.Add("page_size", page_size);
            paraList.Add("page_num", page_num);

            OrganizationResult organization = await this.TGet<OrganizationResult>(urlShopList, paraList);
            return organization;
        }

        #endregion

        #region 会员-会员用总部authority_id

        //全员
        public async Task<ScrmCustomerDto> ScrmCustomerList(int page_no, int is_member, DateTime created_at_start, DateTime created_at_end)
        {
            Dictionary<string, object> paramList = new Dictionary<string, object>();
            paramList.Add("page_size", 50);
            if( is_member >= 0)
            {
                paramList.Add("is_member", 0);  //是否为会员，0表示非会员，1表示会员
            }


            if (page_no > 0)
            {

                paramList.Add("page_no", page_no);
            }

            if (created_at_start != null && created_at_start.Year > 1900)
            {
                paramList.Add("created_at_start", DateTimeUtil.DateTimeToTimeStamp( created_at_start ));
            }

            if (created_at_end != null && created_at_end.Year > 1900)
            {
                paramList.Add("created_at_end", DateTimeUtil.DateTimeToTimeStamp(created_at_end));
            }

            ScrmCustomerDto dto = await this.TGet<ScrmCustomerDto>(urlScrmCustomerList, paramList);

            //HttpResponseMessage httpResponseMessage = await base.GetAsync(requestUri);
            //if (httpResponseMessage.IsSuccessStatusCode)
            //{
            //    string result = await httpResponseMessage.Content.ReadAsStringAsync();
            //    dto = await httpResponseMessage.Content.ReadAsAsync<ScrmCustomerDto>();
            //    if (dto.success)
            //    {
            //        return dto;
            //    }
            //    else
            //    {
            //        ScrmCustomerError error = JsonConvert.DeserializeObject<ScrmCustomerError>(result);
            //        dto.message = error.gw_err_resp.err_msg;
            //        dto.code = error.gw_err_resp.err_code;

            //        //this.WriteInformation("GetScrmCustomerList", $"code:{dto.code} msg:{dto.message}");
            //    }
            //}

            return dto;
        }

        /// <summary>
        /// 更新会员
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<CustomerUpdate3Dto> ScrmCustomerUpdate(CustomerUpdate3Param data)
        {
            CustomerUpdate3Dto dto = await this.TPost<CustomerUpdate3Dto>(urlScrmCustomerUpdate, data);
            return dto;
        }

        /// <summary>
        /// 创建普通用户
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<CustomerCreate3Dto> ScrmCustomerCreate(CustomerCreate3Param param)
        {
            CustomerCreate3Dto dto= await this.TPost<CustomerCreate3Dto>(urlScrmCustomerCreate, param);
            return dto;
        }

        /// <summary>
        /// 创建会员
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<CustomerUpdate3Dto> ScrmCustomerCreateMember(CreateMemberParam data)
        {
            CustomerUpdate3Dto dto = await this.TPost<CustomerUpdate3Dto>(urlScrmCustomerCreateMember, data);
            return dto;
        }

        /// <summary>
        /// 增加会员积分
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<CustomerPointsDto> ScrmCustomerPointsIncrease(CustomerPointsParam data)
        {
            CustomerPointsDto dto = await this.TPost<CustomerPointsDto>(urlScrmCustomerPointsIncrease, data);
            return dto;
        }

        /// <summary>
        /// 减少会员积分
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<CustomerPointsDto> ScrmCustomerPointsDecrease(CustomerPointsParam data)
        {
            CustomerPointsDto dto = await this.TPost<CustomerPointsDto>(urlScrmCustomerPointsDecrease, data);
            return dto;
        }

        /// <summary>
        /// 同步会员积分
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<CustomerPointsDto> ScrmCustomerPointsSync(CustomerPointsSyncParam data)
        {
            CustomerPointsDto dto = await this.TPost<CustomerPointsDto>(urlScrmCustomerPointsSync, data);
            return dto;
        }

        #endregion

        /// <summary>
        /// 更新库存
        /// </summary>
        /// <param name="openStock"></param>
        /// <returns></returns>
        public async Task<OpenStockResult> OpenStock(OpenStock openStock)
        { 
            OpenStockResult stockResult = await this.TPost<OpenStockResult>("", openStock); 
            return stockResult;
        }

        /// <summary>
        /// 批量更新库存
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<ItemUpdateResult> BranchUpdateStock(StockUpdateRequest data)
        { 
            ItemUpdateResult stockResult = await this.TPost<ItemUpdateResult>(urlBranchUpdateStock, data);
            return stockResult;
        }

        /// <summary>
        /// 批量更新价格
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<ItemUpdateResult> BranchUpdatePrice(PriceUpdateRequest data)
        {
            ItemUpdateResult stockResult = await this.TPost<ItemUpdateResult>(urlBranchUpdateStock, data);
            return stockResult;
        }

        public async Task<DecryptsDto> DecryptBatch(List<string> sources)
        {
            try
            {
                Dictionary<string, List<string>> data = new Dictionary<string, List<string>>();
                data.Add("sources", sources);

                string json = JsonConvert.SerializeObject(data);
                StringContent stringContent = new StringContent(json);
                stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

                urlDecryptBatch += "?access_token=" + this.access_token;
                DecryptsDto dto = new DecryptsDto();
                HttpResponseMessage httpResponseMessage = await base.PostAsync(urlDecryptBatch, stringContent);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string result = await httpResponseMessage.Content.ReadAsStringAsync();
                    dto = await httpResponseMessage.Content.ReadAsAsync<DecryptsDto>();
                }

                return dto;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        protected virtual Task<TokenYZYDto> GetToken()
        { 
            return null;
        }

        /// <summary>
        /// 带token的Post
        /// </summary> 
        private async Task<T> TPost<T>(string uriString, object param) where T : new()
        {
            try
            {
                if(this.access_token == "")
                {
                    await this.GetToken();
                }

               
                uriString = uriString + "?access_token=" + this.access_token;

                T dto = new T();
                string json = JsonConvert.SerializeObject(param);
                StringContent stringContent = new StringContent(json);
                stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

                HttpResponseMessage httpResponseMessage = await base.PostAsync(uriString, stringContent);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string STR = await httpResponseMessage.Content.ReadAsStringAsync();

                    dto = await httpResponseMessage.Content.ReadAsAsync<T>(); 
                }
                else
                {
                    throw new Exception(httpResponseMessage.ToString());
                }
                 
                return dto;
            }
            catch (Exception ex)
            { 
                throw ex;
            }
         
        } 
        private async Task<T> TGet<T>(string uriString, Dictionary<string, object> paramList) where T : new()
        {
            if (this.access_token == "")
            {
                await this.GetToken();
            }

            //TokenYZYDto dtoToken = await　this.GetToken();
            //if(dtoToken.code != 200)
            //{
            //    throw new Exception("code:" + dtoToken.code.ToString() + " msg:" + dtoToken.message);
            //}

            string requestUri = uriString ;
            if (paramList == null)
            {
                paramList = new Dictionary<string, object>();
            }

            paramList.Add("access_token", this.access_token);


            string url = GetUrl(requestUri);
            if (paramList != null && paramList.Count > 0)
            {
                url += "?";
                string strParam = "";
                foreach (KeyValuePair<string, object> keyValue in paramList)
                {
                    if (strParam != "")
                    {
                        strParam += "&";
                    }

                    strParam += $"{keyValue.Key}={keyValue.Value}";
                }
                url += strParam;
            }

            HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
            if (!httpResponseMessage.IsSuccessStatusCode)
            {
                throw new Exception(httpResponseMessage.ToString());
            }
            else
            {
                string result = await httpResponseMessage.Content.ReadAsStringAsync();
                return await httpResponseMessage.Content.ReadAsAsync<T>();
            }
        } 
        private string GetUrl(string requestUri)
        {
            string url = base.BaseAddress.OriginalString + requestUri;
            if (!string.IsNullOrEmpty(requestUri) && requestUri.ToLower().Contains("http"))
            {
                url = requestUri;
            }
            return url;
        }
         
        
     
    }
}
